/**
 *
 * @author Craig
 */
import java.awt.*;  //imports the AWT library
import java.awt.event.*;    //imports the events section of AWT library
public class calcMain implements ActionListener, ItemListener
{
    calcFrame frame;    //creates calcFrame object
    MenuBar menu;   //creates menubar object
    Menu about; //creates menu object
    MenuItem author;    //creates menuItem object
    CheckboxGroup checkboxGroup;    //creates checkboxgroup
    Checkbox radians, degrees;  //creates checkbox objects
    TextField display;  //creates a textfield
    Button buttons[] = new Button[20];  //creates an array of buttons 
    Button clearAll, clearEntry, log; //creates button objects
    Button scientificButtons[] = new Button[10];    //creates array of scientific
    boolean addButtonPressed, subtractButtonPressed, multiplyButtonPressed; //creates booleans
    boolean divideButtonPressed, decimalPointPressed, powerButtonPressed;   //booleans
    double initialNumber; //creates a double for the basic operations that require a section entry
    double currentNumber = 0; //creates a double
    int decimalPlaces = 0;  //creates int for decimal places
        
    public static void main (String args[]) //main class
    {
        calcMain calc = new calcMain(); //creates instance of the calculator
        calc.makeCalculator();  //creates GUI of calculator
    }
        
    public void makeCalculator() //class to make the GUI
    {
        final int BWIDTH = 25;  //width of buttons
        final int BHEIGHT = 25; //height of buttons
        int count = 1;  //creates int counter
        frame = new calcFrame("Basic Scientific Calculator");   //creates frame of calculator
        frame.setSize(300,290); //sets the size of the frame
        frame.setBackground(Color.DARK_GRAY);   //sets the background color
        menu = new MenuBar();   //creates a menu on frame
        MenuItem author;    //adds author to menu item
        about = new Menu("About");  //adds about to the menu
        author = new MenuItem("Author");    //adds author as a menu item
        author.addActionListener(this); //adds an action to the author menu item
        about.add(author);  //add author to about
        menu.add(about);    //adds about to the menu
        frame.setMenuBar(menu); // add menubar to the frame
        frame.setLayout(null);  // override the layout manager
           
        for (int row = 0; row < 3; ++row) // set the initial numbers that is 1 to 9
        {
            for (int col = 0; col < 3; ++col) 
            {
                buttons[count] = new Button(Integer.toString(count));
                buttons[count].addActionListener(this);
                buttons[count].setBounds(30*(col + 1), 30*(row + 4),BWIDTH,BHEIGHT);
                buttons[count].setBackground(Color.gray);
                frame.add(buttons[count++]);
            }
        }
        // Now create, addlistener and add to frame all other buttons
        
        //0 button
        buttons[0] = new Button("0");
        buttons[0].addActionListener(this);
        buttons[0].setBounds(30,210,BWIDTH,BHEIGHT);
        buttons[0].setBackground(Color.gray);
        frame.add(buttons[0]);
        
        //decimal button
        buttons[10] = new Button(".");
        buttons[10].addActionListener(this);
        buttons[10].setBounds(60,210,BWIDTH,BHEIGHT);
        buttons[10].setBackground(Color.red);
        frame.add(buttons[10]);
        
        //equals to button
        buttons[11] = new Button("=");
        buttons[11].addActionListener(this);
        buttons[11].setBounds(90,210,BWIDTH,BHEIGHT);
        buttons[11].setBackground(Color.gray);
        frame.add(buttons[11]);
        
        //multiply button
        buttons[12] = new Button("*");
        buttons[12].addActionListener(this);
        buttons[12].setBounds(120,120,BWIDTH,BHEIGHT);
        buttons[12].setBackground(Color.gray);
        frame.add(buttons[12]);
        
        //divide button
        buttons[13] = new Button("/");
        buttons[13].addActionListener(this);
        buttons[13].setBounds(120,150,BWIDTH,BHEIGHT);
        buttons[13].setBackground(Color.gray);
        frame.add(buttons[13]);
        
        //addition button
        buttons[14] = new Button("+");
        buttons[14].addActionListener(this);
        buttons[14].setBounds(120,180,BWIDTH,BHEIGHT);
        buttons[14].setBackground(Color.gray);
        frame.add(buttons[14]);
        
        //subtract button
        buttons[15] = new Button("-");
        buttons[15].addActionListener(this);
        buttons[15].setBounds(120,210,BWIDTH,BHEIGHT);
        buttons[15].setBackground(Color.gray);
        frame.add(buttons[15]);
        
        //reciprocal button
        buttons[16] = new Button("1/x");
        buttons[16].addActionListener(this);
        buttons[16].setBounds(150,120,BWIDTH,BHEIGHT);
        buttons[16].setBackground(Color.gray);
        frame.add(buttons[16]);
        
        //power button
        buttons[17] = new Button("x^n");
        buttons[17].addActionListener(this);
        buttons[17].setBounds(150,150,BWIDTH,BHEIGHT);
        buttons[17].setBackground(Color.gray);
        frame.add(buttons[17]);
        
        //change sign button
        buttons[18] = new Button("+/-");
        buttons[18].addActionListener(this);
        buttons[18].setBounds(150,180,BWIDTH,BHEIGHT);
        buttons[18].setBackground(Color.gray);
        frame.add(buttons[18]);
        
        //factorial button
        buttons[19] = new Button("x!");
        buttons[19].addActionListener(this);
        buttons[19].setBounds(150, 210, BWIDTH, BHEIGHT);
        buttons[19].setBackground(Color.gray);
        frame.add(buttons[19]);
        
        // Clear All button
        clearAll = new Button("Clear AllTest");
        clearAll.addActionListener(this);
        clearAll.setBounds(10, 240, BWIDTH + 30, BHEIGHT);
        clearAll.setBackground(Color.gray);
        frame.add(clearAll);
        
        // Clear Entry button
        clearEntry = new Button("Clear Entry");
        clearEntry.addActionListener(this);
        clearEntry.setBounds(70, 240, BWIDTH + 40, BHEIGHT);
        clearEntry.setBackground(Color.gray);
        frame.add(clearEntry);
        
        // log button
        log = new Button("Log");
        log.addActionListener(this);
        log.setBounds(140, 240, BWIDTH + 20, BHEIGHT);
        log.setBackground(Color.gray);
        frame.add(log);
        
        // set display area for 
        display = new TextField("0");
        display.setBounds(30,90,150,20);
        display.setBackground(Color.white);
        
        // buttons for scientific calculator
        
        // Sine button
        scientificButtons[0] = new Button("Sin");
        scientificButtons[0].addActionListener(this);
        scientificButtons[0].setBounds(180, 120, BWIDTH + 10, BHEIGHT);
        scientificButtons[0].setVisible(true);
        scientificButtons[0].setBackground(Color.gray);
        frame.add(scientificButtons[0]);
        
        // cosine button
        scientificButtons[1] = new Button("Cos");
        scientificButtons[1].addActionListener(this);
        scientificButtons[1].setBounds(180, 150, BWIDTH + 10, BHEIGHT);
        scientificButtons[1].setBackground(Color.gray);
        scientificButtons[1].setVisible(true);
        frame.add(scientificButtons[1]);
        
        // Tan button
        scientificButtons[2] = new Button("Tan");
        scientificButtons[2].addActionListener(this);
        scientificButtons[2].setBounds(180, 180, BWIDTH + 10, BHEIGHT);
        scientificButtons[2].setBackground(Color.gray);
        scientificButtons[2].setVisible(true);
        frame.add(scientificButtons[2]);
        
        // PI button
        scientificButtons[3] = new Button("Pi");
        scientificButtons[3].addActionListener(this);
        scientificButtons[3].setBounds(180, 210, BWIDTH + 10, BHEIGHT);
        scientificButtons[3].setBackground(Color.gray);
        scientificButtons[3].setVisible(true);
        frame.add(scientificButtons[3]);
        
        // arcSine button
        scientificButtons[4] = new Button("aSin");
        scientificButtons[4].addActionListener(this);
        scientificButtons[4].setBounds(220, 120, BWIDTH + 10, BHEIGHT);
        scientificButtons[4].setBackground(Color.gray);
        scientificButtons[4].setVisible(true);
        frame.add(scientificButtons[4]);
        
        // arcCos button
        scientificButtons[5] = new Button("aCos");
        scientificButtons[5].addActionListener(this);
        scientificButtons[5].setBounds(220, 150, BWIDTH + 10, BHEIGHT);
        scientificButtons[5].setBackground(Color.gray);
        scientificButtons[5].setVisible(true);
        frame.add(scientificButtons[5]);
        
        // arcTan button
        scientificButtons[6] = new Button("aTan");
        scientificButtons[6].addActionListener(this);
        scientificButtons[6].setBounds(220, 180, BWIDTH + 10, BHEIGHT);
        scientificButtons[6].setBackground(Color.gray);
        scientificButtons[6].setVisible(true);
        frame.add(scientificButtons[6]);
        
        // e button
        scientificButtons[7] = new Button("e");
        scientificButtons[7].addActionListener(this);
        scientificButtons[7].setBounds(220, 210, BWIDTH + 10, BHEIGHT);
        scientificButtons[7].setBackground(Color.gray);
        scientificButtons[7].setVisible(true);
        frame.add(scientificButtons[7]);
        
        // to degrees button
        scientificButtons[8] = new Button("to deg");
        scientificButtons[8].addActionListener(this);
        scientificButtons[8].setBounds(190, 240, BWIDTH + 20, BHEIGHT);
        scientificButtons[8].setBackground(Color.gray);
        scientificButtons[8].setVisible(true);
        frame.add(scientificButtons[8]);
        
        // to radians button
        scientificButtons[9] = new Button("to rad");
        scientificButtons[9].addActionListener(this);
        scientificButtons[9].setBounds(240, 240, BWIDTH + 20, BHEIGHT);
        scientificButtons[9].setBackground(Color.gray);
        scientificButtons[9].setVisible(true);
        
        //adds scientific buttons
        frame.add(scientificButtons[9]);
        
        //creates checkboxes for degrees and radians
        checkboxGroup = new CheckboxGroup();
        degrees = new Checkbox("Degrees", checkboxGroup, true);
        radians = new Checkbox("Radians", checkboxGroup, false);
        degrees.addItemListener(this);
        radians.addItemListener(this);
        degrees.setBounds(185, 75, 3 * BWIDTH, BHEIGHT);
        radians.setBounds(185, 95, 3 * BWIDTH, BHEIGHT);
        degrees.setVisible(true);
        radians.setVisible(true);
        frame.add(degrees);
        frame.add(radians);
        frame.add(display);
        frame.setVisible(true);
    }
    
    public void actionPerformed(ActionEvent actionEvent) //class to take actions when buttons are pressed
    {
        String buttonText = actionEvent.getActionCommand();//uses the button text to get the command for the button
        double displayNumber = Double.valueOf(display.getText()).doubleValue();//turns value in textfield to double
        
        // if the button pressed text is 0 to 9
        if((buttonText.charAt(0) >= '0') & (buttonText.charAt(0) <= '9')) 
        {
            if(decimalPointPressed) //action if decimal button pressed
            {
                for (int i=1;i <=decimalPlaces; ++i)
                {
                    currentNumber *= 10;
                    currentNumber +=(int)buttonText.charAt(0)- (int)'0';
                }
                
                for (int i=1;i <=decimalPlaces; ++i) 
                {
                    currentNumber /=10;
                }
                
                ++decimalPlaces;
                display.setText(Double.toString(currentNumber));
            }
            else 
            {
                currentNumber = currentNumber * 10 + (int)buttonText.charAt(0)-(int)'0';
                display.setText(Integer.toString((int)currentNumber));
            }
        }
            
        // if button pressed is addition
        if(buttonText.equals("+")) 
        {
            addButtonPressed = true;
            initialNumber = displayNumber;
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // if button pressed is subtract
        if (buttonText.equals("-")) 
        {
            subtractButtonPressed = true;
            initialNumber = displayNumber;
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // if button pressed is divide
        if (buttonText.equals("/")) 
        {
            divideButtonPressed = true;
            initialNumber = displayNumber;
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // if button pressed is multiply
        if (buttonText.equals("*")) 
        {
            multiplyButtonPressed = true;
            initialNumber = displayNumber;
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // if button pressed is reciprocal
        if (buttonText.equals("1/x")) 
        {    
            display.setText(reciprocal(displayNumber)); // call reciprocal method
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // if button is pressed to change a sign
        if (buttonText.equals("+/-")) 
        {
                
            display.setText(changeSign(displayNumber)); // call changesign meyhod to change the sign
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // factorial button
        if (buttonText.equals("x!")) 
        {
            display.setText(factorial(displayNumber));
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        // power button
        if (buttonText.equals("x^n")) 
        {
            powerButtonPressed = true;
            initialNumber = displayNumber;
            currentNumber = 0;
            decimalPointPressed = false;
        }
            

        // sin button
        if (buttonText.equals("Sin")) 
        {
            if (degrees.getState())
            {
                display.setText(Double.toString(Math.sin(Math.PI * displayNumber/180)));
            }
            else 
            {
                display.setText(Double.toString(Math.sin(displayNumber)));
                currentNumber = 0;
                decimalPointPressed = false;
            }
        }

        //cos button
        if (buttonText.equals("Cos")) 
        {
            if (degrees.getState())
            {
                display.setText(Double.toString(Math.cos(Math.PI * displayNumber/180)));
            }
            else
            {
                display.setText(Double.toString(Math.cos(displayNumber)));
                currentNumber = 0;
                decimalPointPressed = false;
            }
        }

        //tan button
        if (buttonText.equals("Tan")) 
        {
            if (degrees.getState())
            {
               display.setText(Double.toString(Math.tan(Math.PI * displayNumber/180)));
            }
            else 
            {
               display.setText(Double.toString(Math.tan(displayNumber)));
               currentNumber = 0;
               decimalPointPressed = false;
            }
        }

        //arcSin button
        if (buttonText.equals("aSin")) 
        {
            if (degrees.getState())
            {
               display.setText(Double.toString(Math.asin(displayNumber)* 180/Math.PI ));  
            }
            else 
            {
               display.setText(Double.toString(Math.asin(displayNumber)));
               currentNumber = 0;
               decimalPointPressed = false;
            }
        }
    
        //arcCos button
        if (buttonText.equals("aCos")) 
        {
            if (degrees.getState())
            {
                display.setText(Double.toString(Math.acos(displayNumber)* 180/Math.PI ));
            }
            else 
            {
                display.setText(Double.toString(Math.acos(displayNumber)));
                currentNumber = 0;
                decimalPointPressed = false;
            }
        }

        //arcTan button
        if (buttonText.equals("aTan")) 
        {
            if (degrees.getState())
            {
                display.setText(Double.toString(Math.atan(displayNumber)* 180/Math.PI ));
            }
            else 
            {
                display.setText(Double.toString(Math.atan(displayNumber)));
                currentNumber = 0;
                decimalPointPressed = false;
            }
        }
        
        // this will convert the numbers displayed to degrees
        if (buttonText.equals("to deg"))
        {
            display.setText(Double.toString(Math.toDegrees(displayNumber)));
        }   
        
        // this will convert the numbers displayed to radians
        if (buttonText.equals("to rad"))
        {
            display.setText(Double.toString(Math.toRadians(displayNumber)));
        }
        
        //pi button
        if (buttonText.equals("Pi")) 
        {
            display.setText(Double.toString(Math.PI));
            currentNumber = 0;
            decimalPointPressed = false;
        }
        
        //Log button
        if (buttonText.equals("Log"))
        {
            if(displayNumber < 0) 
                {
                    MessageBox message = new MessageBox ( frame, "Error ", true, "Non-real Number.");
                    message.show();
                }
                else
                {
                    display.setText(Double.toString(Math.log10(displayNumber)));
                }
            currentNumber = 0;
            decimalPointPressed = false;
        }   
        
        // check if decimal point is pressed
        if (buttonText.equals(".")) 
        {
            String displayedNumber = display.getText();
            boolean decimalPointFound = false;
            int i;
            decimalPointPressed = true;
                
            // check for decimal point
            for (i =0; i < displayedNumber.length(); ++i) 
            {
                if(displayedNumber.charAt(i) == '.') 
                {
                    decimalPointFound = true;
                    continue;
                }
            }
                
            if (!decimalPointFound)
            {
                decimalPlaces = 1;
            }
        }

        //clear all button
        if(buttonText.equals("Clear All"))
        {
            // set all buttons to false
            resetAllButtons();
            display.setText("0");
            currentNumber = 0;
        }

        //clear entry button
        if (buttonText.equals("Clear Entry")) 
        {
            display.setText("0");
            currentNumber = 0;
            decimalPointPressed = false;
        }

        //e button
        if (buttonText.equals("e")) 
        {
            display.setText(Double.toString(Math.E));
            currentNumber = 0;
            decimalPointPressed = false;
        }
            

        // equals button
        if (buttonText.equals("=")) 
        {
            currentNumber = 0;
            // if add button is pressed
            if(addButtonPressed)
            {
                display.setText(Double.toString(initialNumber + displayNumber));
            }
            
            // if subtract button is pressed
            if(subtractButtonPressed)
            {
                display.setText(Double.toString(initialNumber - displayNumber));
            }
            
            // if divide button is pressed
            if (divideButtonPressed) 
            {
                // check if the divisor is zero
                if(displayNumber == 0) 
                {
                    MessageBox message = new MessageBox ( frame, "Error ", true, "Cannot divide by zero.");
                    message.show();
                }
                else
                {
                    display.setText(Double.toString(initialNumber/displayNumber));
                }
            }
                
            // if multiply button is pressed
            if(multiplyButtonPressed)
            {
                display.setText(Double.toString(initialNumber * displayNumber));
            }
            
            // if power button is pressed
            if (powerButtonPressed)
            {
                display.setText(power(initialNumber, displayNumber));
            }
            
            // set all the buttons to false
            resetAllButtons();
        }

        //displays the about message box
        if (buttonText.equals("Author")) 
        {
            MessageBox message = new MessageBox ( frame, "Basic Scientific Calculator for CS 474 Proseminar", true, "Author: Craig Rowe, Andrew Blowe, Richard Garcia, Ryan Huffman");
            message.show();
        }
    }
    
    //method to reset all buttons for next calculation
    public void resetAllButtons() 
    {
        addButtonPressed = false;
        subtractButtonPressed = false;
        multiplyButtonPressed = false;
        divideButtonPressed = false;
        decimalPointPressed = false;
        powerButtonPressed = false;
    }
    
    //method to perform a factorial calculation
    public String factorial(double num) 
    {
        int theNum = (int)num;

        //checks to see if the number is greater than 1 because calculation starts at num - 1
        if (theNum < 1) 
        {
            MessageBox message = new MessageBox (frame, "Facorial Error", true, "Cannot find the factorial of numbers less than 1.");
            message.show();
            return ("0");
        }
        else 
        {
            //calculates the factorial and converts to string
            for (int i=(theNum - 1); i > 1; --i)
            {
                theNum *= i;
                
            }
            return Integer.toString(theNum);
        }
    }

    //method to perform reciprocal of function
    public String reciprocal(double num) 
    {
        //checks to see if the numeber is 0
        if (num ==0) 
        {
            MessageBox message = new MessageBox(frame,"Reciprocal Error", true, "Cannot find the reciprocal of 0");
            message.show();
        }
        else
        {
            num = 1/num;
        }
        return Double.toString(num);
    }
    
    //performs the power function
    public String power (double base, double index) 
    {
        return Double.toString(Math.pow(base, index));
    }

    //changes the sign from positive to negative and vice-versa
    public String changeSign(double num) 
    {
        return Double.toString(-num);
    }

    //makes the scientific buttons visible
    public void itemStateChanged(ItemEvent itemEvent) 
    {
        if (!scientificButtons[0].isVisible()) 
                {
                    for (int i=0; i < 10; ++i)
                    scientificButtons[i].setVisible(true);
                    radians.setVisible(true);
                    degrees.setVisible(true);
                }
    }
}
